package com.sismul.activity;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;

import android.R.array;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.audiofx.Equalizer;

import com.sismul.AppLog;
import com.sismul.App;
import com.sismul.Constants;
import com.sismul.R;
import com.sismul.model.Band;
import com.sismul.model.BandsDataSource;
import com.sismul.model.Recorder;
import com.sismul.model.Word;
import com.sismul.model.WordsDataSource;

public class HomeScreen extends Activity implements TextToSpeech.OnInitListener {

	private Button trainingBtn;
	private Button settingBtn;
	private Button recordingBtn;
	private Button commandBtn;

	private FrameLayout parrot_background;

	private ImageView parrot_flying;

	private boolean isCommand = false;
	private Recorder recorder;

	private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;

	private WordsDataSource datasource;

	private BandsDataSource bandsdatasource;

	private TextToSpeech mTts;

	private String fileLocation;

	private Equalizer mEqualizer;

	private MediaPlayer mMediaPlayer;

	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		// Draw the splash screen
		setContentView(R.layout.homescreen);

		mMediaPlayer = new MediaPlayer();

		datasource = new WordsDataSource(this);
		datasource.open();

		bandsdatasource = new BandsDataSource(this);
		bandsdatasource.open();

		recorder = new Recorder();
		recorder.bufferSize = AudioRecord.getMinBufferSize(
				Constants.RECORDER_SAMPLERATE, Constants.RECORDER_CHANNELS,
				Constants.RECORDER_AUDIO_ENCODING);

		trainingBtn = (Button) findViewById(R.id.trainingBtn);
		settingBtn = (Button) findViewById(R.id.settingBtn);
		recordingBtn = (Button) findViewById(R.id.recordingBtn);
		commandBtn = (Button) findViewById(R.id.commandBtn);

		parrot_background = (FrameLayout) findViewById(R.id.flParrotTop);

		parrot_flying = (ImageView) findViewById(R.id.flying_parrot);

		trainingBtn.setOnClickListener(btnClickHandler);
		settingBtn.setOnClickListener(btnClickHandler);
		recordingBtn.setOnClickListener(btnClickHandler);
		commandBtn.setOnClickListener(btnClickHandler);

		mTts = new TextToSpeech(this, this // TextToSpeech.OnInitListener
		);

		// Check to see if a recognition activity is present
		PackageManager pm = getPackageManager();
		List<ResolveInfo> activities = pm.queryIntentActivities(new Intent(
				RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
		if (activities.size() == 0) {
			App.showDialog(HomeScreen.this,
					"Your device is not supported to run this app.", true);
		}
	}

	protected void onResume() {
		super.onResume();
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// if we get any key, clear the splash screen
		super.onKeyDown(keyCode, event);
		return true;
	}

	public boolean onTouchEvent(MotionEvent event) {
		// if we get any key, clear the splash screen
		super.onTouchEvent(event);
		return true;
	}

	private View.OnClickListener btnClickHandler = new View.OnClickListener() {
		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.trainingBtn: {
				AppLog.logString("Training Button");
				startVoiceRecognitionActivity();
				break;
			}
			case R.id.settingBtn: {
				AppLog.logString("Setting Button");
				Intent intent = new Intent("com.sismul.activity.SETTINGSCREEN");
				startActivity(intent);

				break;
			}
			case R.id.recordingBtn: {
				AppLog.logString("Recording Button");

				if (!recorder.isRecording) {
					disableButtons();
					enableStopRecordingButton();
					recorder.startRecording();
				} else {
					disableStopRecordingButton();
					enableButtons();
					recorder.stopRecording();
					Intent intent = new Intent("com.sismul.activity.SETTINGSCREEN");
					startActivity(intent.putExtra("fileLocation", recorder.fileLocation));
				}

				break;
			}
			case R.id.commandBtn: {
				AppLog.logString("Command Button");
				isCommand = true;
				startVoiceRecognitionActivity();

			}
			}
		}
	};

	private void enableButtons() {
		trainingBtn.setEnabled(true);
		settingBtn.setEnabled(true);
	}

	private void disableButtons() {
		trainingBtn.setEnabled(false);
		settingBtn.setEnabled(false);
	}

	private void enableStopRecordingButton() {
		recordingBtn.setText("Stop");
	}

	private void disableStopRecordingButton() {
		recordingBtn.setText("I speech");
	}

	/**
	 * Fire an intent to start the speech recognition activity.
	 */
	private void startVoiceRecognitionActivity() {
		Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
		intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
				RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
		intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
				"Please, say something ...");
		startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
	}

	/**
	 * Handle the results from the recognition activity.
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == VOICE_RECOGNITION_REQUEST_CODE
				&& resultCode == RESULT_OK) {
			// Fill the list view with the strings the recognizer thought it
			// could have heard
			if (isCommand == false) {
				ArrayList<String> matches = data
						.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);

				// assumption : first match is always match :)
				if (matches.size() > 0) {
					Log.e("words", matches.get(0));
					String[] words = matches.get(0).split(" ");
					String fullWord = "";

					for (int i = 0; i < words.length; i++) {
						Log.e("word", words[i]);
						datasource.createWord(words[i]);
						fullWord += say(words[i]) + " ";
					}
					saveToFile(fullWord);
					// playAudio();
					mTts.speak(fullWord, TextToSpeech.QUEUE_ADD, // Drop all
																	// pending
																	// entries
																	// in
							// the playback queue.
							null);
				}

			} else {
				ArrayList<String> matches = data
						.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
				if (matches.size() > 0) {
					Log.e("words", matches.get(0));
					AnimationDrawable parrot_flying_Animation;
					if (matches.get(0).equalsIgnoreCase("fly")) {
						parrot_flying
								.setBackgroundResource(R.anim.parrot_flying);
						parrot_flying_Animation = (AnimationDrawable) parrot_flying
								.getBackground();
						parrot_flying_Animation.start();
					}
					if (matches.get(0).equalsIgnoreCase("dont fly")
							|| matches.get(0).equalsIgnoreCase("come down")
							|| matches.get(0).equalsIgnoreCase("don't fly")) {
						parrot_flying
								.setBackgroundResource(R.drawable.bird_home);
					}
				}
				isCommand = false;
			}
			/*
			 * mList.setAdapter(new ArrayAdapter<String>(this,
			 * android.R.layout.simple_list_item_1, matches));
			 */
		}

		super.onActivityResult(requestCode, resultCode, data);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(1, 1, 0, "Exit").setIcon(R.drawable.ic_menu_logout);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case 1:
			// TODO : implement this
			finish();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	// Implements TextToSpeech.OnInitListener.
	public void onInit(int status) {
		// status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
		if (status == TextToSpeech.SUCCESS) {
			// Set preferred language to US english.
			// Note that a language may not be available, and the result will
			// indicate this.
			int result = mTts.setLanguage(Locale.US);
			// Try this someday for some interesting results.
			// int result mTts.setLanguage(Locale.FRANCE);
			if (result == TextToSpeech.LANG_MISSING_DATA
					|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
				// Lanuage data is missing or the language is not supported.
				Log.e("TTS", "Language is not available.");
				App.showDialog(HomeScreen.this,
						"Your device is not supported to run this app.", true);
			}
		} else {
			// Initialization failed.
			App.showDialog(HomeScreen.this,
					"Your device is not supported to run this app.", true);
			Log.e("TTS", "Could not initialize TextToSpeech.");
		}
	}

	private static final String[] vocal = { "a", "i", "u", "e", "o" };

	private String say(String word) {
		Random rand = new Random();
		ArrayList<String> vocal_in_word;
		vocal_in_word = SearchArray(word, vocal);
		String[] temp_word;
		Word w = datasource.get(word);
		int counter = (w == null) ? 0 : w.getCount();
		if (counter < 3) {
			for (int i = 0; i < vocal_in_word.size(); i++) {
				String a = vocal_in_word.get(i);
				temp_word = word.split(a);
				word = "";
				for (int j = 0; j < temp_word.length; j++) {
					if (j != 0)
						word = word + vocal_in_word.get(i) + temp_word[i];
					else
						word = temp_word[j] + vocal[rand.nextInt(vocal.length)];
				}
			}
		}
		return word;
		// mTts.speak(word, TextToSpeech.QUEUE_ADD, // Drop all pending entries
		// in
		// the playback queue.
		// null);
	}

	private ArrayList<String> SearchArray(String word, String[] vocal) {
		ArrayList<String> temp = new ArrayList<String>();
		for (int i = 0; i < vocal.length; i++) {
			if (word.contains(vocal[i])) {
				temp.add(vocal[i]);
			}
		}
		return temp;

	}

	private void saveToFile(String word) {
		fileLocation = App.getFilename();
		mTts.synthesizeToFile(word, null, fileLocation);
	}

	@Override
	public void onDestroy() {
		// Don't forget to shutdown!
		if (mTts != null) {
			mTts.stop();
			mTts.shutdown();
		}

		super.onDestroy();
	}

	public void playAudio() {
		// Create the MediaPlayer
		Log.e("FileLocation", fileLocation);
		try {
			mMediaPlayer.reset();
			mMediaPlayer.setDataSource(fileLocation);
			Log.e("trace", "0");
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		AppLog.logString("MediaPlayer audio session ID: "
				+ mMediaPlayer.getAudioSessionId());

		// Create the Equalizer object (an AudioEffect subclass) and attach it
		// to our media player,
		// with a default priority (0).
		Log.e("trace", "1");
		mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
		Log.e("trace", "2");
		mEqualizer.setEnabled(true);
		Log.e("trace", "3");
		short bands = mEqualizer.getNumberOfBands();
		Log.e("trace", "4");
		final short minEQLevel = mEqualizer.getBandLevelRange()[0];
		Log.e("trace", "5");
		for (short i = 0; i < bands; i++) {
			final short band = i;
			int progress = 0;
			Band bandInstance;
			if ((bandInstance = bandsdatasource.get((long) i)) == null) {
				progress = mEqualizer.getBandLevel(band);
			} else {
				progress = bandInstance.getLevel() - minEQLevel;
			}
			Log.e("trace", "6");
			mEqualizer.setBandLevel(band, (short) (minEQLevel + progress));
			Log.e("trace", "7");
		}
		Log.e("trace", "8");
		try {
			mMediaPlayer.prepare();

		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		mMediaPlayer.start();
		Log.e("trace", "9");
	}

	@Override
	protected void onPause() {
		super.onPause();

		if (isFinishing() && mMediaPlayer != null) {
			mEqualizer.release();
			mMediaPlayer.release();
			mMediaPlayer = new MediaPlayer();
		}
	}
}
